feat(scripts): add policy release status and dispatch tooling - #261
Conversation
Add two scripts under scripts/policy-release/ to manage policy releases: - policy_release_status.py: fetches upstream tags and reports each policy's release status to a CSV, including inter-policy go.mod dependency waves, release reason, and stale-pin detection. - release_policies.py: dispatches the Release Policy workflow via gh in dependency-wave order, async within a wave with status reporting, and holds back policies with stale dependency pins (dispatch-only). Also git-ignore the generated CSV and Python caches. Signed-off-by: Renuka Fernando <renukapiyumal@gmail.com>
Distinguish go and python policies in policy_release_status.py: - add policy_type column (go/python/unknown) detected as the release workflow does - scope go.mod dependency analysis to go policies; python policies have no inter-policy deps and land in wave 0 - add version_files_consistent column and gate python release_ready on pyproject.toml matching the yaml version, with an anomaly warning - update README to document the new columns and python handling Signed-off-by: Renuka Fernando <renukapiyumal@gmail.com>
|
Warning Review limit reached
Next review available in: 21 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
📝 WalkthroughSummary
WalkthroughAdds tooling that scans policy metadata, tags, commits, versions, and Go dependencies to generate a release-status CSV. It derives dependency release waves, readiness, stale pins, and propagated release requirements. A second script consumes the CSV to dry-run or dispatch GitHub Actions workflows by wave, monitor results, and stop before later waves when a release fails. Documentation and ignore rules describe and support the workflow. Sequence Diagram(s)sequenceDiagram
participant PolicyReleaseStatus
participant StatusCSV
participant ReleasePolicies
participant GitHubActions
PolicyReleaseStatus->>StatusCSV: Generate policy release status
ReleasePolicies->>StatusCSV: Read release-ready rows and waves
ReleasePolicies->>GitHubActions: Dispatch workflows for each wave
GitHubActions-->>ReleasePolicies: Provide run status
ReleasePolicies->>GitHubActions: Watch dispatched runs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (3)
scripts/policy-release/release_policies.py (2)
200-212: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueConcurrent
gh run watchoutput may interleave.
watch()streams directly to the console (capture=False) from multiple threads at once; output from concurrent runs can interleave in the terminal. Cosmetic only — final per-policy status is still printed correctly afterward.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@scripts/policy-release/release_policies.py` around lines 200 - 212, Update the concurrent watch flow around watch() and ThreadPoolExecutor so each run’s gh output is captured or otherwise synchronized before being written to the console, preventing interleaved output from multiple threads. Preserve the existing results mapping and final per-policy status behavior.
108-115: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win
watch()conflates infra errors with workflow failure.Any non-zero exit from
gh run watch(including transient network/auth issues) is reported as"failure", which halts subsequent waves the same as a genuine workflow failure. This matches the documented fail-safe intent, but distinguishingghCLI errors from an actual failed run conclusion (e.g., viagh run view --json conclusion) would avoid unnecessarily blocking releases on transient tooling issues.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@scripts/policy-release/release_policies.py` around lines 108 - 115, Update watch() so non-zero gh run watch exits are distinguished from genuine workflow failures: query the completed run’s conclusion using gh run view --json conclusion, and only return "failure" when the workflow conclusion indicates failure. Preserve the existing (run_id, conclusion) return contract while representing transient gh CLI or infrastructure errors separately so they do not get treated as workflow failures.scripts/policy-release/policy_release_status.py (1)
99-114: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winConsider real parsers instead of hand-rolled regex extraction.
read_yaml_name_versionandread_pyproject_versionextract values via line-anchored regex rather thanyaml.safe_load/tomllib. This works for the simple unquoted scalars in this repo today, but is fragile against quoted strings, inline comments, or non-top-level indentation — any of which would silently corruptpolicy_name/yaml_version/pyproject_versionand cascade into wrong release-readiness computations.♻️ Sketch using standard parsers
import tomllib def read_pyproject_version(policy_dir: Path): pyproject = policy_dir / "pyproject.toml" if not pyproject.exists(): return None with open(pyproject, "rb") as f: data = tomllib.load(f) return data.get("project", {}).get("version")Also applies to: 149-159
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@scripts/policy-release/policy_release_status.py` around lines 99 - 114, Replace the hand-rolled regex parsing in read_yaml_name_version and read_pyproject_version with real parsers: use the repository’s YAML parser with safe loading for policy-definition.yaml and tomllib.load for pyproject.toml. Read only the intended top-level YAML name/version and project.version TOML fields, preserve the existing missing-file/absent-value behavior, and return parsed values without corruption from quoting, comments, or indentation.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@scripts/policy-release/policy_release_status.py`:
- Around line 52-56: Update run() to propagate subprocess command failures
instead of returning empty output: invoke subprocess.run with failure checking
enabled and preserve stderr in the resulting exception or otherwise surface it
to callers. Keep successful commands returning stripped stdout, while ensuring
downstream functions such as fetch_upstream_tags, get_all_policy_tags, and
commits_since_tag receive an error rather than interpreting failed commands as
empty data.
In `@scripts/policy-release/release_policies.py`:
- Around line 64-105: The dispatch function should use the run ID returned by
the gh workflow run command instead of polling latest_run_id and comparing it
with before. Update the command invocation/output parsing to capture GitHub
Actions’ created run ID, return that ID on success, and remove the latest-run
polling logic from dispatch while preserving failure handling.
---
Nitpick comments:
In `@scripts/policy-release/policy_release_status.py`:
- Around line 99-114: Replace the hand-rolled regex parsing in
read_yaml_name_version and read_pyproject_version with real parsers: use the
repository’s YAML parser with safe loading for policy-definition.yaml and
tomllib.load for pyproject.toml. Read only the intended top-level YAML
name/version and project.version TOML fields, preserve the existing
missing-file/absent-value behavior, and return parsed values without corruption
from quoting, comments, or indentation.
In `@scripts/policy-release/release_policies.py`:
- Around line 200-212: Update the concurrent watch flow around watch() and
ThreadPoolExecutor so each run’s gh output is captured or otherwise synchronized
before being written to the console, preventing interleaved output from multiple
threads. Preserve the existing results mapping and final per-policy status
behavior.
- Around line 108-115: Update watch() so non-zero gh run watch exits are
distinguished from genuine workflow failures: query the completed run’s
conclusion using gh run view --json conclusion, and only return "failure" when
the workflow conclusion indicates failure. Preserve the existing (run_id,
conclusion) return contract while representing transient gh CLI or
infrastructure errors separately so they do not get treated as workflow
failures.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 48774962-60b8-4ac0-a559-4d2110afca16
📒 Files selected for processing (4)
.gitignorescripts/policy-release/README.mdscripts/policy-release/policy_release_status.pyscripts/policy-release/release_policies.py
Address review findings in the policy release tooling: - policy_release_status.py: run() now surfaces non-zero command exits instead of returning "" (silently misread as no tags/commits); git fetch is a hard failure to avoid reporting against stale local tags. - release_policies.py: dispatch() parses the run URL returned by gh workflow run (gh >= 2.87.0) for exact run-id attribution, falling back to polling on older gh; watch() queries the authoritative conclusion so transient gh/network errors are not reported as workflow failures. Signed-off-by: Renuka Fernando <renukapiyumal@gmail.com>
Purpose
Releasing policies today means manually checking, per policy, whether there are unreleased commits since the last git tag, whether the policy-definition.yaml version is bumped, and — for policies that depend on each other via go.mod — in what order to release them. This PR adds tooling to automate that analysis and to drive releases through the existing Release Policy workflow in dependency order.
Approach
scripts/policy-release/policy_release_status.py: fetches tags fromupstream, inspects every policy, and writes a git-ignoredpolicy-release-status.csv(uploadable to Google Sheets for further analysis).pyproject.tomlmatches the yaml version.vprefix so they feed straight into the release workflow.scripts/policy-release/release_policies.py: reads the CSV and dispatches the Release Policy workflow viagh, wave by wave.--executeperforms the dispatch.scripts/policy-release/README.mddocumenting both scripts, all CSV columns, flags, and the dependency/safety model.Related Issues
N/A
Checklist
Remarks
The scripts have been validated end-to-end against the current repository state: the status script produces the CSV (55 policies: 52 go, 3 python), and the release script dry-run correctly plans wave 0 releases and holds back
mcp-authdue to a stalejwt-authpin.--executedispatches againstwso2/gateway-controllersby default and therefore requires workflow-dispatch permission on that repo.